#!/usr/bin/env bash
# mindbender-snapshot -- Produce a snapshot of the current DeepDive app
# > mindbender snapshot [SNAPSHOT_CONFIG]
#
# Author: Jaeho Shin <netj@cs.stanford.edu>
# Created: 2015-02-09
set -eu

# find path to the DeepDive app based on the snapshot path
DEEPDIVE_APP=$(find-deepdive-app)
export DEEPDIVE_APP
cd "$DEEPDIVE_APP"

ConfigName=${1:-default}
[[ $# -eq 0 ]] || shift
SnapshotDir=${1:-}
[[ $# -eq 0 ]] || shift

# figure out snapshot configuration file name
if [[ -e "$ConfigName" ]]; then
    snapshotConfiguration=$ConfigName
else
    snapshotConfiguration="$DEEPDIVE_APP"/snapshot-"$ConfigName".conf
fi

if ! [[ -e "$snapshotConfiguration" ]]; then
    # install default snapshot configuration derived from DeepDive's application.conf if not there
    dashboard-snapshot-config generate default
    error "Default dashboard snapshot configuration was installed to the DeepDive app $DEEPDIVE_APP" || true
    snapshotConfiguration="$DEEPDIVE_APP"/snapshot-default.conf
fi

# some sanity checks before proceeding
dburi=$(find-deepdive-db-uri)
deepdive sql "SELECT 1" >/dev/null ||
    error "Cannot run queries against the database at $dburi"

if [[ -z "$SnapshotDir" ]]; then
    # create a fresh snapshot directory
    SnapshotDir=snapshot/$(date +%Y%m%d)
    serial=1
    while [[ -e "$SnapshotDir-$serial" ]]; do
        let ++serial
    done
    SnapshotDir="$SnapshotDir-$serial"
elif [[ -L "$SnapshotDir" ]]; then
    SnapshotDir=$(cd "$SnapshotDir" && pwd -P)
    SnapshotDir=${SnapshotDir#$DEEPDIVE_APP/}
fi
mkdir -p "$SnapshotDir"/files

# display the snapshot ID
echo "${SnapshotDir#snapshot/}"

{ # nothing should go into stdout from the rest

# record as latest failure if RUNNING symlink exists
if [[ -L snapshot/RUNNING ]]; then
    pgidFile=snapshot/"$(readlink snapshot/RUNNING)".RUNNING
    if [[ -e "$pgidFile" ]] && ps -g $(head -1 "$pgidFile") &>/dev/null; then
        : still running
    else
        rm -f "$pgidFile"
        mv -f snapshot/RUNNING snapshot/ABORTED
    fi
fi
# keep a symlink to this snapshot
ln -sfnv "${SnapshotDir#snapshot/}" snapshot/RUNNING

# keep a copy of important deepdive artifacts
[[ -e snapshot-files ]] ||
    cp -f "$MINDBENDER_HOME"/etc/snapshot-files .
sed 's/#.*//' <snapshot-files | grep -v '^$' |
xargs -I{} -- cp -a {} "$SnapshotDir"/files/
# TODO avoid copying files more than once into snapshot and create symlink to a master copy instead

# record process group id
echo $(ps -o pgid= -p $$) >"$SnapshotDir".RUNNING

# cleanup RUNNING
cleanupRUNNING() {
    # remove the RUNNING symlink as well as the process group id
    ! [[ snapshot/RUNNING -ef "$SnapshotDir" ]] || rm -f snapshot/RUNNING
    rm -f "$SnapshotDir".RUNNING
}
trap 'cleanupRUNNING' EXIT

# keep a symlink to the last aborted one if any error happens
trap 'ln -sfnv "${SnapshotDir#snapshot/}" snapshot/ABORTED' ERR

# produce reports for the snapshot
mindbender-produce-reports "$SnapshotDir" "$snapshotConfiguration"

# bookkeep symlinks to the latest, previous snapshots
if [[ -e snapshot/LATEST && ! snapshot/LATEST -ef snapshot/PREVIOUS ]]; then
    rm -f snapshot/PREVIOUS
    mv -f snapshot/LATEST snapshot/PREVIOUS
fi
ln -sfnv "${SnapshotDir#snapshot/}" snapshot/LATEST

} >&2
